<?php
/**
 * @author Akulov Denis <akulov.d.g@gmail.com>
 * @since 03.07.2011
 */
class MVC_Builder {


    /**
     * @var MVC_Path_Interface
     */
    private $_objMvcPath = null;


    /**
     * @var Container_Interface
     */
    private $_objContainer = null;


    /**
     * @var boolean
     */
    private $_isMainMvcNode = false;


    private function isMainMvcNode () {
        return $this->_isMainMvcNode;
    }


    public function __construct (Container_Interface $container) {
        $this->_objContainer = $container;
    }


    public function SetIsMainMvcNode ($bYes) {
        return $this->_isMainMvcNode = $bYes;
    }


    public function setMvcPath (MVC_Path_Interface $path) {
        $this->_objMvcPath = $path;
    }


    /**
     * @return MVC_Path_Interface
     */
    private function getMvcPath () {
        return $this->_objMvcPath;
    }


    /**
     * @return MVC_Controller_Base
     */
    private function newController () {
        $controller =
            $this->getConfig()->getAttribute('PREFIX', 'CONTROLLER').
            $this->getContoller();
        return new $controller();
    }


    /**
     * @return Config_Interface
     */
    private function getConfig () {
        return $this->_objContainer->get('Config');
    }


    /**
     * @return Container_Interface
     */
    private function getContainer () {
        return $this->_objContainer;
    }


    private function getContoller () {
        return $this->getMvcPath()->getController();
    }


    private function getMethod () {
        return $this->getMvcPath()->getMethod();
    }


    private function getMethodPost () {
        return $this->getMvcPath()->getMethodPost();
    }



    /**
     * @return MVC_ModelLoader_Interface
     */
    private function getModelLoader () {
        return $this->getContainer()->get('MVC_ModelLoader');
    }


    private function isAllowedFunction () {
        $objAccess = $this->getModelLoader()->getModel('ACL_Access');
        return $objAccess->isAllowed(
            $this->getContoller(),
            $this->getMethod(),
            $this->getParam()
        );
    }


    private function getParam () {
        return $this->getMvcPath()->getParam();
    }


    private function athorization() {
        /* @var $objSession Container_OnlyRead_Interface */
        $objSession = $this->getContainer()->get('SESSION');

        if ($objSession->isExists('login') && $objSession->isExists('password')) {
            /* @var $objAthorizationData M_ACL_AthorizationData_Interface */
            $objAthorizationData = $this->getModelLoader()->getModel('ACL_AthorizationData');

            $objAthorizationData->setLogin($objSession->get('login'));
            $objAthorizationData->setPassword($objSession->get('password'));

            /* @var $objUser ACL_User_Interface */
            $objUser = $this->getModelLoader()->getModel('ACL_User');

            $objUser->athorization($objAthorizationData);
        }
    }


    private function throwExceptionIfMethodNotExists ($objController, $strMethodName) {
        if (!method_exists($objController, $strMethodName)) {
            throw new Exception('Not found MVC-node: {'.$this->getContoller().'/'.$strMethodName.'}');
        }
    }


    public function build () {
        /* @var $objUser ACL_User_Interface */
        $objUser = $this->getModelLoader()->getModel('ACL_User');

        if ($objUser->getLogin() == '@guest') {
            $this->athorization();
        }

        $objController = $this->newController();

        $objController->_setContainer($this->getContainer());
        $objController->_setView(new MVC_View_Container($this->getConfig()));

        if (!$this->isAllowedFunction()) {
            $objController->_accessDeniedHandler($this->getMethod(), $this->getParam());
            return $objController->_getResult();
        }

        if (!$this->getContainer()->get('POST')->isEmpty() && $this->isMainMvcNode()) {
            $this->throwExceptionIfMethodNotExists($objController, $this->getMethodPost());
            call_user_func_array(array($objController, $this->getMethodPost()), $this->getParam());
            return $objController->_getResult();
        }

        $this->throwExceptionIfMethodNotExists($objController, $this->getMethod());
        call_user_func_array(array($objController, $this->getMethod()), $this->getParam());
        return $objController->_getResult();
    }

}